#include "GridMesh.h"
#include "LionSceneManager.h"
#include "LionActor.h"
#include "LionVertexLayoutManager.h"

using namespace Lion;

EDGridMesh::EDGridMesh()
{
    m_pActor = SceneManager::getSingleton().spawnActor("EDGridMesh");
    m_pMeshComponent = LCast<DynamicMeshComponent>(m_pActor->addComponent(DynamicMeshComponent::GetComponentType(), "EDGridMesh"));

    VertexLayoutData layoutDesc;
    layoutDesc.addElement(0, 0, VertexElement::FORMAT_RGB32_FLOAT, VertexElement::USAGE_POSITION);
    layoutDesc.addElement(0, 12, VertexElement::FORMAT_RGBA8_UNORM, VertexElement::USAGE_ATTRIBUTE);
    VertexLayoutPtr vertexLayoutPtr = VertexLayoutManager::getSingleton().createVertexLayout(layoutDesc);

    m_pMeshComponent->setVertexLayout(vertexLayoutPtr);

    m_pMeshComponent->setVertexBufferCount(1);

    const s32 segment = 11;
    const s32 halfSegment = segment / 2;

    HardwareBufferPtr vertexBufferPtr = HardwareBufferPtr(LION_NEW_T(HardwareBuffer));
    {
        vertexBufferPtr->createBuffer(sizeof(RenderVertex), segment * 2 * 2 + 4, HardwareBufferData::HBU_VERTEX_GPU_R, false, false);

        RenderVertex* vertices = LION_NEW_ARRAY_T(RenderVertex, vertexBufferPtr->getNumElements());
        Vector4U8 vertexColor(180, 180, 180, 255);

        RenderVertex* pV = vertices;
        for (s32 x = 0; x < segment; x++)
        {
            if (x == halfSegment)
            {
                pV->xyz = Vector3F32(-halfSegment, 0.0f, 0.0f);
                pV->color = vertexColor;
                pV++;

                pV->xyz = Vector3F32(0.0f, 0.0f, 0.0f);
                pV->color = vertexColor;
                pV++;
            }
            else
            {
                pV->xyz = Vector3F32(-halfSegment, 0.0f, x - halfSegment);
                pV->color = vertexColor;
                pV++;

                pV->xyz = Vector3F32(halfSegment, 0.0f, x - halfSegment);
                pV->color = vertexColor;
                pV++;
            }
        }

        for (s32 z = 0; z < segment; z++)
        {
            if (z == halfSegment)
            {
                pV->xyz = Vector3F32(0.0f, 0.0f, -halfSegment);
                pV->color = vertexColor;
                pV++;

                pV->xyz = Vector3F32(0.0f, 0.0f, 0.0f);
                pV->color = vertexColor;
                pV++;
            }
            else
            {
                pV->xyz = Vector3F32(z - halfSegment, 0.0f, -halfSegment);
                pV->color = vertexColor;
                pV++;

                pV->xyz = Vector3F32(z - halfSegment, 0.0f, halfSegment);
                pV->color = vertexColor;
                pV++;
            }
        }

        // red x
        {
            pV->xyz = Vector3F32(0.0f, 0.0f, 0.0f);
            pV->color = Vector4U8(255, 0, 0, 255);
            pV++;

            pV->xyz = Vector3F32(halfSegment, 0.0f, 0.0f);
            pV->color = Vector4U8(255, 0, 0, 255);
            pV++;
        }
        
        // blue z
        {
            pV->xyz = Vector3F32(0.0f, 0.0f, 0.0f);
            pV->color = Vector4U8(0, 0, 255, 255);
            pV++;

            pV->xyz = Vector3F32(0.0f, 0.0f, halfSegment);
            pV->color = Vector4U8(0, 0, 255, 255);
            pV++;
        }

        LION_ASSERT(s32(pV - vertices) == vertexBufferPtr->getNumElements());

        vertexBufferPtr->setElements((u8*)vertices);
    }

    BoxBound boxBound(Vector3F32(-halfSegment * 2, 0.0f, -halfSegment * 2), Vector3F32(halfSegment * 2, 0.0f, halfSegment * 2));

    m_pMeshComponent->createSurfaces(1);
    m_pMeshComponent->setSurfaceRangeInMesh(0, 0, vertexBufferPtr->getNumElements());
    m_pMeshComponent->setBounds(boxBound);
    m_pMeshComponent->setSurfaceBounds(0, boxBound);

    m_pMeshComponent->setVertexBuffer(0, vertexBufferPtr);

    m_pMeshComponent->setSurfaceOperationType(0, ROT_LINELIST);

    MaterialPtr materialPtr = MaterialManager::getSingleton().loadResource("ed_gridMesh");
    if (!materialPtr.isNull())
    {
        m_pMeshComponent->setSurfaceMaterial(0, materialPtr);
    }
}

EDGridMesh::~EDGridMesh()
{
    SceneManager::getSingleton().destroyActor(m_pActor);
}

